package app.models.system;

import com.ifonly.activerecord.DbUtils;
import com.ifonly.activerecord.Model;
import com.ifonly.activerecord.Record;
import com.ifonly.activerecord.annotation.Table;
import com.ifonly.activerecord.annotation.Tx;
import com.ifonly.activerecord.sql.config.Sql;
import com.ifonly.cache.CacheKeyHandler;
import com.ifonly.cache.SimpleCacheKeyHandler;
import com.ifonly.cache.annotation.Cacheable;
import com.ifonly.cache.annotation.Cachevict;

import java.lang.reflect.Method;
import java.util.List;

/**
 * @author <a href="mailto:ifonlymaster@163.com">ifonly</a>
 * @version 1.0 2016-01-08 16:50
 * @since JDK 1.6
 */
@Table(name = "s_role_resource")
public class RoleResource extends Model {
    private static final long serialVersionUID = -8107708435399800654L;

    /**
     * 根据 role id 获取 资源列表
     *
     * @param roleId RoleId
     * @return Resource List
     */
    @Cacheable(name = "RoleResourceCache", key = "findResourcesByRoleId",
            cacheKeyHandler = SimpleCacheKeyHandler.class)
    public List<Resource> findResourcesByRoleId(Integer roleId) {
        return findResourcesByRoleId(roleId, 0);
    }

    /**
     * 根据 roleId, resource pid 获取 资源列表
     *
     * @param roleId      role id
     * @param resourcePId resource pid
     * @return Resource List
     */
    private List<Resource> findResourcesByRoleId(Integer roleId, int resourcePId) {
        List<Resource> resources = DbUtils.list(Resource.class, Sql.get("roleResource.findResourcesByRoleId"), roleId, resourcePId);

        if (resources != null && !resources.isEmpty()) {
            for (Resource resource : resources) {
                int pid = resource.getInteger("id");
                List<Resource> children = findResourcesByRoleId(roleId, pid);
                resource.put("children", children);
            }
        }
        return resources;
    }

    /**
     * 查询所有的 Resource, 同时关联上 Role
     *
     * @param roleId roleId
     * @return Record List
     */
    @Cacheable(name = "RoleResourceCache", key = "resourcesWithRole",
            cacheKeyHandler = RoleResourceCacheKeyHandler.class)
    public List<Record> findResourcesWithRole(int roleId) {
        return DbUtils.list(Sql.get("roleResource.findResourcesWithRole"), roleId);
    }

    /**
     * 保存 role
     *
     * @param role Role
     * @param resourceIds resource for role
     */
    @Tx
    @Cachevict(name = "RoleResourceCache", key = "resourcesWithRole", cacheKeyHandler = RoleResourceCacheKeyHandler.class)
    public void saveRoleWithResource(Role role, String resourceIds) {
        if (DbUtils.isNew(role)) {
            role.saveReturnGeneratedKey();
        } else {
            role.update();
        }

        int roleId = role.getInt("id");
        DbUtils.delete(Sql.get("roleResource.deleteRoleResource"), roleId);
        String[] ids = resourceIds.split(",");

        int len = ids.length;
        if (len != 0) {
            Object[][] params = new Object[len][];
            for (int i = 0; i < len; i++) {
                params[i] = new Object[] {roleId, ids[i]};
            }
            DbUtils.insertBatch(Sql.get("roleResource.insertRoleResource"), params);
        }
    }

    @Tx
    @Cachevict(name = "RoleResourceCache", key = "resourcesWithRole", cacheKeyHandler = RoleResourceCacheKeyHandler.class)
    public void deleteRoleWithResource(int roleId) {
        DbUtils.delete(Sql.get("roleResource.deleteRoleResource"), roleId);
        DbUtils.delete(Sql.get("role.deleteRole"), roleId);
    }

    /**
     * RoleResourceCacheKeyHandler 用于处理 RoleResourceCache  resourcesWithRole 缓存
     */
    public static class  RoleResourceCacheKeyHandler implements CacheKeyHandler {
        @Override
        public String handle(String key, Object target, Method method, Object[] args) {
            if (key == null) {
                key = "";
            }

            if (args != null && args.length > 0) {
                if (method.getName().equals("findResourcesWithRole")) {
                    int roleId = (Integer) args[0];
                    key = key + "-" + roleId;
                } else if(method.getName().equals("saveRoleWithResource")) {
                    Role role = (Role) args[0];
                    if (role != null) {
                        int roleId = role.getInt("id", 0);
                        key = key + "-" + roleId;
                    }
                }
            }
            return key;
        }
    }

}
